package com.example.demo.utils;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.example.demo.mapper.FundAccountMapper;
import com.example.demo.mapper.StockPositionsMapper;
import com.example.demo.pojo.Accounts.FundAccounts;
import com.example.demo.pojo.Order.CreatOrderPojo;
import com.example.demo.pojo.Stock.StockPositions;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.math.RoundingMode;

import static com.example.demo.utils.ConstantUtils.*;

@Service
public class StockPositionsUtils {

    @Resource
    private StockPositionsMapper stockPositionsMapper;

    @Resource
    private FundAccountMapper fundAccountMapper;

    private StockPositionsUtils stockPositionsUtils;

    private static Logger logger = LogManager.getLogger();

    //当凌晨的时候自动刷新冻结股票数量
    @Scheduled(cron = "0 0 0 * * ?")
    @Transactional
    public void resetFrozenFund() {
        stockPositionsMapper.resetFrozenQuantity();
    }

    // 查询持仓信息并返回持仓对象
    public StockPositions getStockPositions(Integer id, Integer userId, String stockCode, String market) {
        QueryWrapper<StockPositions> stockPositionsQueryWrapper = new QueryWrapper<>();
        stockPositionsQueryWrapper
                .eq("position_id", id)
                .eq("user_id", userId)
                .eq("stock_code", stockCode)
                .eq("market", market);
        return stockPositionsMapper.selectOne(stockPositionsQueryWrapper);
    }

    // 查询持仓信息并返回持仓对象，通过用户id,大赛id,股票代码stockcode可唯一确定持仓对象
    public StockPositions getStockPositionsNew(Integer userId, Integer competitionId, String stockCode) {
        QueryWrapper<StockPositions> stockPositionsQueryWrapper = new QueryWrapper<>();
        stockPositionsQueryWrapper
                .eq("user_id", userId)
                .eq("competition_id",competitionId)
                .eq("stock_code", stockCode);
        return stockPositionsMapper.selectOne(stockPositionsQueryWrapper);
    }


    //修改卖出时持仓信息(补充,如果卖出所有数量则移除这只股票)
    public boolean updateStockPositionsAfterTransaction(
            Integer id,
            Integer userId,
            String stockCode,
            String market,
            int quantity,
            int multiply,
            BigDecimal price) {

        // 创建查询条件
        UpdateWrapper<StockPositions> stockPositionsUpdateWrapper = new UpdateWrapper<>();
        stockPositionsUpdateWrapper
                .eq("position_id", id)
                .eq("user_id", userId)
                .eq("stock_code", stockCode)
                .eq("market", market);

        // 查询持仓信息
        StockPositions stockPositions = stockPositionsMapper.selectOne(stockPositionsUpdateWrapper);

        // 计算卖出数量
        int sellQuantity = quantity / multiply;

        // 更新持仓数量
        stockPositions.setQuantity(stockPositions.getQuantity() - sellQuantity);

        // 如果持仓数量小于0，则抛出异常
        if (stockPositions.getQuantity() < 0) {
            return false; // 卖出数量不能超过持仓数量，操作失败
        }

        // 更新可用数量
        stockPositions.setAvailableQuantity(stockPositions.getAvailableQuantity() - sellQuantity);


        // 更新总价值
        stockPositions.setPositionValue(BigDecimal.ZERO);

        // 更新市场价值
        stockPositions.setMarketValue(BigDecimal.ZERO);

        // 其他属性保持不变
        stockPositions.setFrozenQuantity(stockPositions.getFrozenQuantity()); // 根据需要更新冻结数量
        stockPositions.setPositionProfitLoss(stockPositions.getPositionProfitLoss());
        stockPositions.setLatestPrice(stockPositions.getLatestPrice());
        stockPositions.setProfitLossRatio(stockPositions.getProfitLossRatio());
        stockPositions.setPositionRatio(stockPositions.getPositionRatio());

        // 更新数据库中的持仓信息
        int stockPositionsUpdate = stockPositionsMapper.update(stockPositions, stockPositionsUpdateWrapper);

        return stockPositionsUpdate > 0; // 如果更新成功返回true，否则返回false
    }

    //新,修改卖出时持仓信息(补充,如果卖出所有数量则移除这只股票)
    public boolean updateStockPositionsAfterTransactionNew(
            CreatOrderPojo creatOrderPojo,
            Integer userId,
            Integer orderType) {

        int competitionid = creatOrderPojo.getCompetitionid();
        String stockCode = creatOrderPojo.getStockCode();
        String market = creatOrderPojo.getMarket();
        int quantity = creatOrderPojo.getQuantity();
        BigDecimal price = creatOrderPojo.getPrice();

        // 创建查询条件 ,通过用户id,比赛id,股票代码可唯一确定一张StockPositions表
        UpdateWrapper<StockPositions> stockPositionsUpdateWrapper = new UpdateWrapper<>();
        stockPositionsUpdateWrapper
                .eq("user_id", userId)
                .eq("competition_id", competitionid)
                .eq("stock_code", stockCode);


        // 查询持仓信息
        StockPositions stockPositions = stockPositionsMapper.selectOne(stockPositionsUpdateWrapper);

        // 即时卖出时更新以下字段
        if(orderType.equals(3)){
            // 更新可用数量
            stockPositions.setAvailableQuantity(stockPositions.getAvailableQuantity() - quantity);
            // 如果持仓数量小于0，则抛出异常
            if (stockPositions.getAvailableQuantity() < 0) {
                logger.info("卖出数量超过持仓数量，操作失败!");
                return false; // 卖出数量不能超过持仓数量，操作失败
            }
            // 如果持仓数量已为0，则删除该表并返回
            if (stockPositions.getAvailableQuantity()==0){
                int deleteById = stockPositionsMapper.deleteById(stockPositions);
                logger.info("持仓数量已为0，删除该StockPositions表!");
                return deleteById>0;
            }

            // 更新持仓数量
            stockPositions.setQuantity(stockPositions.getAvailableQuantity()+stockPositions.getFrozenQuantity());

            // 计算成本价 如果是即时买入，则进行以下操作:
            // 首先，先把先前的成本价取出来，并获得持仓数量，两者相乘，
            // 再加上本次挂单价和挂单数量，两者亦相乘
            // 最后把两个乘积相减然后除以（先前数量-这次购买的数量），即得最新成本价
            BigDecimal costPrice1 = stockPositions.getCostPrice();
            BigDecimal quantity1 = BigDecimal.valueOf(stockPositions.getQuantity());

            BigDecimal costprice2 = creatOrderPojo.getPrice();
            BigDecimal quantity2 = BigDecimal.valueOf(quantity);

            stockPositions.setCostPrice((costPrice1.multiply(quantity1)
                    .subtract(costprice2.multiply(quantity2)))
                    .divide(quantity1.subtract(quantity2),BigDecimal.ROUND_CEILING)
                    .setScale(2, RoundingMode.HALF_UP));

            // 计算持仓市值,为最新价* 持仓数量
            stockPositions.setPositionValue(creatOrderPojo.getLast()
                    .multiply(BigDecimal.valueOf(stockPositions.getQuantity()))
                    .setScale(2, RoundingMode.HALF_UP));
            // 更新市场价值
            stockPositions.setMarketValue(stockPositions.getPositionValue());
            // 最新价
            stockPositions.setLatestPrice(creatOrderPojo.getLast());

            // 此股持仓盈亏 当前（最新价-成本价）乘以该股持仓数量
            stockPositions.setPositionProfitLoss((creatOrderPojo.getLast()
                    .subtract(stockPositions.getCostPrice()))
                    .multiply(BigDecimal.valueOf(stockPositions.getQuantity()))
                    .setScale(2, RoundingMode.HALF_UP));

            // 查询FundAccounts表，获取持仓总市值和持仓总盈亏
            // 查询平台账户信息,使用大赛id和用户id可唯一确定一张表
            UpdateWrapper<FundAccounts> fundAccountsQueryWrapper = new UpdateWrapper<>();
            fundAccountsQueryWrapper.eq("competition_id", creatOrderPojo.getCompetitionid())
                    .eq("user_id", userId);
            FundAccounts fundAccounts = fundAccountMapper.selectOne(fundAccountsQueryWrapper);

            // 该股持仓占比,为该股当前市值/总市值
            stockPositions.setPositionRatio(stockPositions.getPositionValue()
                    .divide(fundAccounts.getPositionValue(),BigDecimal.ROUND_CEILING)
                    .setScale(2, RoundingMode.HALF_UP));

            // 此股盈亏比例,为该股盈亏/总盈亏
            // 特殊情况，总盈亏刚好为0，那么这时直接给stockPositions中的ProfitLossRatio赋0
            if ((fundAccounts.getPositionProfitLoss().compareTo(BigDecimal.ZERO))==0){
                stockPositions.setProfitLossRatio(BigDecimal.ZERO);
            }
            else {
                stockPositions.setProfitLossRatio(stockPositions.getPositionProfitLoss()
                        .divide(fundAccounts.getPositionProfitLoss(), BigDecimal.ROUND_CEILING)
                        .setScale(2, RoundingMode.HALF_UP));
            }

            // 更新数据库中的持仓信息
            int stockPositionsUpdate = stockPositionsMapper.update(stockPositions, stockPositionsUpdateWrapper);

            return stockPositionsUpdate > 0; // 如果更新成功返回true，否则返回false

        }

        // 更新持仓数量
        stockPositions.setQuantity(stockPositions.getQuantity() - quantity);
        // 如果持仓数量小于0，则抛出异常
        if (stockPositions.getQuantity() < 0) {
            return false; // 卖出数量不能超过持仓数量，操作失败
        }
        // 如果持仓数量已为0，则删除该表并返回
        if (stockPositions.getQuantity()==0){
            int deleteById = stockPositionsMapper.deleteById(stockPositions);
            return deleteById>0;
        }
        // 更新可用数量
        stockPositions.setAvailableQuantity(stockPositions.getAvailableQuantity() - quantity);

        // 更新冻结数量
        stockPositions.setFrozenQuantity(stockPositions.getFrozenQuantity()+quantity);

        // 更新数据库中的持仓信息
        int stockPositionsUpdate = stockPositionsMapper.update(stockPositions, stockPositionsUpdateWrapper);

        return stockPositionsUpdate > 0; // 如果更新成功返回true，否则返回false
    }

    //修改买入时持仓信息
    public boolean updateStockPositionsAfterBuyTransaction(
            Integer id,
            Integer userId,
            String stockCode,
            String market,
            int quantity,
            int multiply,
            BigDecimal price) {

        // 创建查询条件
        UpdateWrapper<StockPositions> stockPositionsUpdateWrapper = new UpdateWrapper<>();
        stockPositionsUpdateWrapper
                .eq("position_id", id)
                .eq("user_id", userId)
                .eq("stock_code", stockCode)
                .eq("market", market);

        // 查询持仓信息
        StockPositions stockPositions = stockPositionsMapper.selectOne(stockPositionsUpdateWrapper);

        // 计算成本价
        BigDecimal firstStockPositionsQuantity = BigDecimal.valueOf(stockPositions.getQuantity());
        BigDecimal divide = BigDecimal.valueOf(quantity).divide(BigDecimal.valueOf(multiply), 0, RoundingMode.HALF_UP);
        BigDecimal stockPositionsQuantity = BigDecimal.valueOf(stockPositions.getQuantity()).add(divide);
        BigDecimal multiply2 = divide.multiply(price);
        stockPositions.setCostPrice((stockPositions.getCostPrice()
                .multiply(firstStockPositionsQuantity)
                .add(multiply2))
                .divide(stockPositionsQuantity)
                .setScale(2, RoundingMode.HALF_UP));

        // 计算总持仓数
        stockPositions.setQuantity(stockPositions.getQuantity() + (quantity / multiply));

        // 计算冻结数量
        stockPositions.setFrozenQuantity(stockPositions.getFrozenQuantity() + (quantity / multiply));

        // 计算总价值
        stockPositions.setPositionValue(stockPositions.getPositionValue()
                .add(multiply2));

        // 市场价格
        stockPositions.setMarketValue(stockPositions.getMarketValue().add(multiply2));

        // 更新持仓信息
        int stockPositionsUpdate = stockPositionsMapper.update(stockPositions, stockPositionsUpdateWrapper);

        return stockPositionsUpdate > 0; // 如果更新成功返回true，否则返回false
    }

    // 新，修改买入时持仓信息(第二次以上买入)
    public boolean updateStockPositionsAfterBuyTransactionNew(
            CreatOrderPojo creatOrderPojo,
            Integer userId,
            Integer orderType
        ){

        //获取订单类型，即时买入,1 限价买入,2 即时卖出,3 限价卖出,4
//        Integer orderType = stockPositionsUtils.getOrderType(creatOrderPojo);
//      上面这条也会报空指针问题，所以我直接传入

        // 查询所需基本信息
        int competitionid = creatOrderPojo.getCompetitionid();
        String stockCode = creatOrderPojo.getStockCode();
        String market = creatOrderPojo.getMarket();
        int quantity = creatOrderPojo.getQuantity();
        BigDecimal price = creatOrderPojo.getPrice();

        // 创建查询条件
        UpdateWrapper<StockPositions> stockPositionsUpdateWrapper = new UpdateWrapper<>();
        stockPositionsUpdateWrapper
                .eq("user_id", userId)
                .eq("competition_id", competitionid)
                .eq("stock_code", stockCode);

        // 查询持仓信息
        StockPositions stockPositions = stockPositionsMapper.selectOne(stockPositionsUpdateWrapper);

        stockPositions.setLatestPrice(creatOrderPojo.getLast());

        // 以下操作，如果为限价买入则不进行相应的更新，放入flink中处理

        if(orderType.equals(1)) {
            // 计算成本价 如果是即时买入，则进行以下操作:
            // 首先，先把先前的成本价取出来，并获得持仓数量，两者相乘，
            // 再加上本次挂单价和挂单数量，两者亦相乘
            // 最后把两个乘积加起来然后除以先前数量和这次购买的数量，即得最新成本价
            BigDecimal costPrice1 = stockPositions.getCostPrice();
            BigDecimal quantity1 = BigDecimal.valueOf(stockPositions.getQuantity());

            BigDecimal costprice2 = creatOrderPojo.getPrice();
            BigDecimal quantity2 = BigDecimal.valueOf(quantity);

            stockPositions.setCostPrice((costPrice1.multiply(quantity1)
                    .add(costprice2.multiply(quantity2)))
                    .divide(quantity1.add(quantity2),BigDecimal.ROUND_CEILING)
                    .setScale(2, RoundingMode.HALF_UP));

            // 计算冻结数量
            stockPositions.setFrozenQuantity(stockPositions.getFrozenQuantity() + quantity);
            // 计算总持仓数
            stockPositions.setQuantity(stockPositions.getQuantity()+stockPositions.getFrozenQuantity());
            // 计算总市值 原总市值 + 最新价*本次购买数量
            stockPositions.setPositionValue(stockPositions.getPositionValue()
                    .add(creatOrderPojo.getLast().multiply(quantity2))
                    .setScale(2, RoundingMode.HALF_UP));
            // 一样是总市值
            stockPositions.setMarketValue(stockPositions.getPositionValue());

            // 此股持仓盈亏 当前（最新价-成本价）乘以该股持仓数量
            stockPositions.setPositionProfitLoss((creatOrderPojo.getLast()
                    .subtract(stockPositions.getCostPrice()))
                    .multiply(BigDecimal.valueOf(stockPositions.getQuantity()))
                    .setScale(2, RoundingMode.HALF_UP));

            // 查询FundAccounts表，获取持仓总市值和持仓总盈亏
            // 查询平台账户信息,使用大赛id和用户id可唯一确定一张表
            UpdateWrapper<FundAccounts> fundAccountsQueryWrapper = new UpdateWrapper<>();
            fundAccountsQueryWrapper.eq("competition_id", creatOrderPojo.getCompetitionid())
                    .eq("user_id", userId);
            FundAccounts fundAccounts = fundAccountMapper.selectOne(fundAccountsQueryWrapper);

            // 该股持仓占比,为该股当前市值/总市值
            stockPositions.setPositionRatio(stockPositions.getPositionValue()
                    .divide(fundAccounts.getPositionValue(),BigDecimal.ROUND_CEILING)
                    .setScale(2, RoundingMode.HALF_UP));

            // 此股盈亏比例,为该股盈亏/总盈亏
            // 特殊情况，总盈亏刚好为0，那么这时直接给stockPositions中的ProfitLossRatio赋0
            if ((fundAccounts.getPositionProfitLoss().compareTo(BigDecimal.ZERO))==0){
                stockPositions.setProfitLossRatio(BigDecimal.ZERO);
            }
            else {
                stockPositions.setProfitLossRatio(stockPositions.getPositionProfitLoss()
                        .divide(fundAccounts.getPositionProfitLoss(), BigDecimal.ROUND_CEILING)
                        .setScale(2, RoundingMode.HALF_UP));
            }

        }

        // 更新持仓信息
        int stockPositionsUpdate = stockPositionsMapper.update(stockPositions, stockPositionsUpdateWrapper);

        return stockPositionsUpdate > 0; // 如果更新成功返回true，否则返回false
    }

    //第一次购买次股票
    public boolean createStockPosition(
            Integer id,
            Integer userId,
            String stockName,
            String market,
            String stockCode,
            int quantity,
            int multiply,
            BigDecimal price) {

        // 创建新的持仓信息
        StockPositions stockPositions = new StockPositions();
        stockPositions.setPositionId(id);
        stockPositions.setUserId(userId);
        stockPositions.setStockName(stockName);
        stockPositions.setMarket(market);
        stockPositions.setStockCode(stockCode);

        // 计算持仓数量
        stockPositions.setQuantity(quantity / multiply);

        // 可用数量为0
        stockPositions.setAvailableQuantity(0);

        // 计算冻结数量
        stockPositions.setFrozenQuantity(quantity / multiply);

        // 计算持仓市值(现在手头的股票市值)
        BigDecimal positionValue = price.multiply(BigDecimal.valueOf(quantity).divide(BigDecimal.valueOf(multiply), 0, RoundingMode.HALF_UP));
        stockPositions.setPositionValue(positionValue);

        // 成本价等于购入价格
        stockPositions.setCostPrice(price);

        // 市场价值等于持仓市值
        stockPositions.setMarketValue(positionValue);

        // 设置其他属性
        stockPositions.setPositionProfitLoss(BigDecimal.ZERO);
        stockPositions.setLatestPrice(BigDecimal.ZERO);
        stockPositions.setProfitLossRatio(BigDecimal.ZERO);
        stockPositions.setPositionRatio(BigDecimal.ZERO);

        // 插入新的持仓信息
        int insert = stockPositionsMapper.insert(stockPositions);

        return insert > 0; // 如果插入成功返回true，否则返回false
    }

    //新，第一次购买此股票
    public boolean createStockPositionNew(
        CreatOrderPojo creatOrderPojo,
        int userId) {

        int competitionid = creatOrderPojo.getCompetitionid();
        String stockCode = creatOrderPojo.getStockCode();
        String stockName = creatOrderPojo.getStockName();
        String market = creatOrderPojo.getMarket();
        int quantity = creatOrderPojo.getQuantity();
        BigDecimal price = creatOrderPojo.getPrice();

        // 创建新的持仓信息
        StockPositions stockPositions = new StockPositions();
        stockPositions.setUserId(userId);
        stockPositions.setCompetitionId(competitionid);
        stockPositions.setStockCode(stockCode);
        stockPositions.setStockName(stockName);
        stockPositions.setMarket(market);

        // 计算持仓数量
        stockPositions.setQuantity(quantity);

        // 可用数量为0
        stockPositions.setAvailableQuantity(0);

        // 计算冻结数量
        stockPositions.setFrozenQuantity(quantity);

        // 成本价等于购入价格
        stockPositions.setCostPrice(price);

        // 最新价
        stockPositions.setLatestPrice(creatOrderPojo.getLast());

        // 计算持仓市值 最新价*持仓数量
        stockPositions.setPositionValue(creatOrderPojo.getLast()
                .multiply(BigDecimal.valueOf(quantity))
                .setScale(2, RoundingMode.HALF_UP));

        // 市场价值等于持仓市值
        stockPositions.setMarketValue(stockPositions.getPositionValue());

        // 此股持仓盈亏 当前（最新价-成本价）乘以该股持仓数量
        stockPositions.setPositionProfitLoss((creatOrderPojo.getLast()
                .subtract(stockPositions.getCostPrice()))
                .multiply(BigDecimal.valueOf(stockPositions.getQuantity()))
                .setScale(2, RoundingMode.HALF_UP));

        // 查询FundAccounts表，获取持仓总市值和持仓总盈亏
        // 查询平台账户信息,使用大赛id和用户id可唯一确定一张表
        UpdateWrapper<FundAccounts> fundAccountsQueryWrapper = new UpdateWrapper<>();
        fundAccountsQueryWrapper.eq("competition_id", creatOrderPojo.getCompetitionid())
                .eq("user_id", userId);
        FundAccounts fundAccounts = fundAccountMapper.selectOne(fundAccountsQueryWrapper);

        // 该股持仓占比,为该股当前市值/总市值
        stockPositions.setPositionRatio(stockPositions.getPositionValue()
                .divide(fundAccounts.getPositionValue(),BigDecimal.ROUND_CEILING)
                .setScale(2, RoundingMode.HALF_UP));

        // 此股盈亏比例,为该股盈亏/总盈亏
        // 特殊情况，总盈亏刚好为0，那么这时直接给stockPositions中的ProfitLossRatio赋0
        if ((fundAccounts.getPositionProfitLoss().compareTo(BigDecimal.ZERO))==0){
            stockPositions.setProfitLossRatio(BigDecimal.ZERO);
        }
        else {
            stockPositions.setProfitLossRatio(stockPositions.getPositionProfitLoss()
                    .divide(fundAccounts.getPositionProfitLoss(), BigDecimal.ROUND_CEILING)
                    .setScale(2, RoundingMode.HALF_UP));
        }
        // 插入新的持仓信息
        int insert = stockPositionsMapper.insert(stockPositions);

        return insert > 0; // 如果插入成功返回true，否则返回false
    }

    public Integer getOrderType(CreatOrderPojo creatOrderPojo) {
        //即时买入
        if (BUY.equals(creatOrderPojo.getOrderType()) && MARKET_ORDER.equals(creatOrderPojo.getOrderStatus())) {
            return 1;
        }
        //限价买入
        if (BUY.equals(creatOrderPojo.getOrderType()) && LIMIT_ORDER.equals(creatOrderPojo.getOrderStatus())) {
            return 2;
        }
        //即时卖出
        if (SELL.equals(creatOrderPojo.getOrderType()) && MARKET_ORDER.equals(creatOrderPojo.getOrderStatus())) {
            return 3;
        }
        //限价卖出
        if (BUY.equals(creatOrderPojo.getOrderType()) && LIMIT_ORDER.equals(creatOrderPojo.getOrderStatus())) {
            return 4;
        }
        return -1;
    }

    //    即时买入,1 限价买入,2 即时卖出,3 限价卖出,4
    public String setOrdersOrderType(Integer orderType) {
        switch (orderType) {
            case 1:
                return "即时买入";
            case 2:
                return "限价买入";
            case 3:
                return "即时卖出";
            case 4:
                return "限价卖出";
            default:
                return "未知类型";
        }
    }

}
